use std::rc::Rc;
use std::sync::Arc;
use std::thread;

use crate::gen_title;

pub fn ch4_8_1() {
    gen_title("ch4_8_1", 18);

    let s = String::from("hello, world");
    let a = Box::new(s);
    // let b = Box::new(s);

    println!("{}", a);
    // println!("{}", b);
}

pub fn ch4_8_2() {
    gen_title("ch4_8_2", 18);

    let a = Rc::new(String::from("hello, world"));
    let b = Rc::clone(&a);

    assert_eq!(2, Rc::strong_count(&a));
    assert_eq!(Rc::strong_count(&a), Rc::strong_count(&b));
    println!("{}", a);
    println!("{}", b);
}

pub fn ch4_8_3() {
    gen_title("ch4_8_3", 18);

    let a = Rc::new(String::from("test ref counting"));
    println!("count after creating a = {}", Rc::strong_count(&a));
    let b = Rc::clone(&a);
    println!("count after creating b = {}", Rc::strong_count(&a));
    {
        let c = Rc::clone(&a);
        println!("count after creating c = {}", Rc::strong_count(&a));
    }

    println!("count after c goes out of scope = {}", Rc::strong_count(&a));
}

pub fn ch4_8_4() {
    gen_title("ch4_8_4", 18);

    struct Owner {
        name: String,
    }

    struct Gadget {
        id: i32,
        owner: Rc<Owner>,
    }

    let gadget_owner: Rc<Owner> = Rc::new(Owner {
        name: "Gadget Man".to_string(),
    });

    let gadget1 = Gadget {
        id: 1,
        owner: Rc::clone(&gadget_owner),
    };

    let gadget2 = Gadget {
        id: 2,
        owner: Rc::clone(&gadget_owner),
    };

    drop(gadget_owner);

    println!(
        "Gadget {} has an owner named {}",
        gadget1.id, gadget1.owner.name
    );
    println!(
        "Gadget {} has an owner named {}",
        gadget2.id, gadget2.owner.name
    );
}

pub fn ch4_8_5() {
    gen_title("ch4_8_5", 18);

    let s = Arc::new(String::from("多线程漫游者"));
    for _ in 0..10 {
        let s = Arc::clone(&s);
        let handle = thread::spawn(move || {
            println!("{}", s);
        });
    }
}
